﻿using Sunny.UI.Win32;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using static AutoTestSystem.KeyboardHookLib;
using System.Net;
using System.Windows.Forms;

namespace AutoTestSystem
{
    /// <summary>
    /// 键盘Hook管理类,
    /// </summary>
    public class KeyboardHookLib
    {
        private const int WH_KEYBOARD_LL = 13; //键盘

        //键盘处理事件委托 ,当捕获键盘输入时调用定义该委托的方法.
        private delegate int HookHandle(int nCode, int wParam, IntPtr lParam);

        //客户端键盘处理事件
        public delegate void ProcessKeyHandle(HookStruct param, out bool handle);

        //接收SetWindowsHookEx返回值
        private static int _hHookValue = 0;

        //勾子程序处理事件
        private HookHandle _KeyBoardHookProcedure;

        //Hook结构
        [StructLayout(LayoutKind.Sequential)]
        public class HookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }

        //设置钩子
        [DllImport("user32.dll")]
        private static extern int SetWindowsHookEx(int idHook, HookHandle lpfn, IntPtr hInstance, int threadId);

        //取消钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        private static extern bool UnhookWindowsHookEx(int idHook);

        //调用下一个钩子
        [DllImport("user32.dll")]
        private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);

        //获取当前线程ID
        [DllImport("kernel32.dll")]
        private static extern int GetCurrentThreadId();

        //Gets the main module for the associated process.
        [DllImport("kernel32.dll")]
        private static extern IntPtr GetModuleHandle(string name);

        private IntPtr _hookWindowPtr = IntPtr.Zero;

        //构造器
        public KeyboardHookLib() { }

        //外部调用的键盘处理事件
        private static ProcessKeyHandle _clientMethod = null;

        /// <summary>
        /// 安装勾子
        /// </summary>
        /// <param name="hookProcess">外部调用的键盘处理事件</param>
        public void InstallHook(ProcessKeyHandle clientMethod)
        {
            _clientMethod = clientMethod;

            // 安装键盘钩子
            if (_hHookValue == 0)
            {
                _KeyBoardHookProcedure = new HookHandle(OnHookProc);

                _hookWindowPtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);

                _hHookValue = SetWindowsHookEx(
                WH_KEYBOARD_LL,
                _KeyBoardHookProcedure,
                _hookWindowPtr,
                0);

                //如果设置钩子失败.
                if (_hHookValue == 0) UninstallHook();
            }
        }

        //取消钩子事件
        public void UninstallHook()
        {
            if (_hHookValue != 0)
            {
                bool ret = UnhookWindowsHookEx(_hHookValue);
                if (ret) _hHookValue = 0;
            }
        }

        //钩子事件内部调用,调用_clientMethod方法转发到客户端应用。
        private static int OnHookProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            {
                //转换结构
                HookStruct hookStruct = (HookStruct)Marshal.PtrToStructure(lParam, typeof(HookStruct));

                if (_clientMethod != null)
                {
                    bool handle = false;
                    //调用客户提供的事件处理程序。
                    _clientMethod(hookStruct, out handle);
                    if (handle) return 1; //1:表示拦截键盘,return 退出
                }
            }
            return CallNextHookEx(_hHookValue, nCode, wParam, lParam);
        }

    }


    public class MouseHookLib
    {
        private const int WH_MOUSE_LL = 14; //键盘

        //键盘处理事件委托 ,当捕获键盘输入时调用定义该委托的方法.
        private delegate int HookHandle(int nCode, int wParam, IntPtr lParam);

        //客户端键盘处理事件
        public delegate void ProcessKeyHandle(MouseHookStruct param, out bool handle);

        //接收SetWindowsHookEx返回值
        private static int _hHookValue = 0;

        //勾子程序处理事件
        private HookHandle _KeyBoardHookProcedure;

        [StructLayout(LayoutKind.Sequential)]
        public class MouseHookStruct
        {
            public Point pt;
            public int vkCode;
            public int scanCode;
            public int hWnd;
            public int wHitTestCode;
            public int dwExtraInfo;
        }


        //设置钩子
        [DllImport("user32.dll")]
        private static extern int SetWindowsHookEx(int idHook, HookHandle lpfn, IntPtr hInstance, int threadId);

        //取消钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        private static extern bool UnhookWindowsHookEx(int idHook);

        //调用下一个钩子
        [DllImport("user32.dll")]
        private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);

        //获取当前线程ID
        [DllImport("kernel32.dll")]
        private static extern int GetCurrentThreadId();

        //Gets the main module for the associated process.
        [DllImport("kernel32.dll")]
        private static extern IntPtr GetModuleHandle(string name);

        private IntPtr _hookWindowPtr = IntPtr.Zero;

        //构造器
        public MouseHookLib() { }

        //外部调用的键盘处理事件
       // private static ProcessKeyHandle _clientMethod = null;

        /// <summary>
        /// 安装勾子
        /// </summary>
        /// <param name="hookProcess">外部调用的键盘处理事件</param>
        public void InstallHook()
        {
            //_clientMethod = clientMethod;

            // 安装键盘钩子
            if (_hHookValue == 0)
            {
                _KeyBoardHookProcedure = new HookHandle(MouseHookProc);

                _hookWindowPtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);

                _hHookValue = SetWindowsHookEx(
                WH_MOUSE_LL,
                _KeyBoardHookProcedure,
                _hookWindowPtr,
                0);

                //如果设置钩子失败.
                if (_hHookValue == 0) UninstallHook();
            }
        }

        //取消钩子事件
        public void UninstallHook()
        {
            if (_hHookValue != 0)
            {
                bool ret = UnhookWindowsHookEx(_hHookValue);
                if (ret) _hHookValue = 0;
            }
        }

        //鼠标事件映射
        private const int WM_MOUSEMOVE = 0x200;
        private const int WM_LBUTTONDOWN = 0x201;
        private const int WM_RBUTTONDOWN = 0x204;
        private const int WM_MBUTTONDOWN = 0x207;
        private const int WM_LBUTTONUP = 0x202;
        private const int WM_RBUTTONUP = 0x205;
        private const int WM_MBUTTONUP = 0x208;
        private const int WM_LBUTTONDBLCLK = 0x203;
        private const int WM_RBUTTONDBLCLK = 0x206;
        private const int WM_MBUTTONDBLCLK = 0x209;


        ////钩子事件内部调用,调用_clientMethod方法转发到客户端应用。
        //private int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam)
        //{
        //    MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
        //    int x = MyMouseHookStruct.pt.X;
        //    int y = MyMouseHookStruct.pt.Y;

        //    if (wParam == WM_LBUTTONDOWN)
        //    {
        //        //鼠标左键按下要进行的处理
        //    }
        //    return CallNextHookEx(_hHookValue, nCode, wParam, lParam);
        //}


        ////钩子事件内部调用,调用_clientMethod方法转发到客户端应用。
        //private static int MouseHookProc(int nCode, int wParam, IntPtr lParam)
        //{
        //    if (nCode >= 0)
        //    {
        //        //转换结构
        //        MouseHookStruct hookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));

        //        if (_clientMethod != null)
        //        {
        //            bool handle = false;
        //            //调用客户提供的事件处理程序。
        //            _clientMethod(hookStruct, out handle);
        //            if (handle) return 1; //1:表示拦截键盘,return 退出
        //        }
        //    }
        //    return CallNextHookEx(_hHookValue, nCode, wParam, lParam);
        //}

        public event MouseEventHandler MouseDown;
        //public event MouseEventHandler MouseUp;
        private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            {
                MouseHookStruct hookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));

                MouseEventArgs e = null;
                switch (wParam)
                {
                    case WM_LBUTTONDOWN:
                        e = new MouseEventArgs(MouseButtons.Left, 1, hookStruct.pt.X, hookStruct.pt.Y, 0);
                        MouseDown(this, e);
                        break;
                    //case WM_RBUTTONDOWN:
                    //    e = new MouseEventArgs(MouseButtons.Right, 1, hookStruct.pt.X, hookStruct.pt.Y, 0);
                    //    MouseDown(this, e);
                    //    break;
                    //case WM_LBUTTONUP:
                    //    e = new MouseEventArgs(MouseButtons.Left, 1, hookStruct.pt.X, hookStruct.pt.Y, 0);
                    //    MouseUp(this, e);
                    //    break;
                    //case WM_RBUTTONUP:
                    //    e = new MouseEventArgs(MouseButtons.Right, 1, hookStruct.pt.X, hookStruct.pt.Y, 0);
                    //    MouseUp(this, e);
                    //    break;
                    default:
                        break;
                }
            }

            return CallNextHookEx(_hHookValue, nCode, wParam, lParam);
        }


    }
}
